home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / blstroid.c < prev    next >
C/C++ Source or Header  |  2000-04-04  |  11KB  |  451 lines

  1. /***************************************************************************
  2.  
  3.   vidhrdw/blstroid.c
  4.  
  5.   Functions to emulate the video hardware of the machine.
  6.  
  7. ****************************************************************************
  8.  
  9.     Playfield encoding
  10.     ------------------
  11.         1 16-bit word is used
  12.  
  13.         Word 1:
  14.             Bits 13-15 = palette
  15.             Bits  0-12 = image number
  16.  
  17.  
  18.     Motion Object encoding
  19.     ----------------------
  20.         4 16-bit words are used
  21.  
  22.         Word 1:
  23.             Bits  7-15 = vertical position
  24.             Bits  0-3  = vertical size of the object, in tiles
  25.  
  26.         Word 2:
  27.             Bit  15    = horizontal flip
  28.             Bit  14    = vertical flip
  29.             Bits  0-13 = image index
  30.  
  31.         Word 3:
  32.             Bits  3-11 = link to the next motion object
  33.  
  34.         Word 4:
  35.             Bits  6-15 = horizontal position
  36.             Bits  0-3  = motion object palette
  37.  
  38. ***************************************************************************/
  39.  
  40. #include "driver.h"
  41. #include "machine/atarigen.h"
  42. #include "vidhrdw/generic.h"
  43.  
  44. #define XCHARS 40
  45. #define YCHARS 30
  46.  
  47. #define XDIM (XCHARS*16)
  48. #define YDIM (YCHARS*8)
  49.  
  50.  
  51.  
  52. /*************************************
  53.  *
  54.  *    Statics
  55.  *
  56.  *************************************/
  57.  
  58. static UINT32 priority[8];
  59.  
  60.  
  61.  
  62. /*************************************
  63.  *
  64.  *    Prototypes
  65.  *
  66.  *************************************/
  67.  
  68. static const UINT8 *update_palette(void);
  69.  
  70. static void pf_color_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  71. static void pf_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  72. static void pf_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  73.  
  74. static void mo_color_callback(const UINT16 *data, const struct rectangle *clip, void *param);
  75. static void mo_render_callback(const UINT16 *data, const struct rectangle *clip, void *param);
  76.  
  77.  
  78.  
  79. /*************************************
  80.  *
  81.  *    Generic video system start
  82.  *
  83.  *************************************/
  84.  
  85. int blstroid_vh_start(void)
  86. {
  87.     static struct atarigen_mo_desc mo_desc =
  88.     {
  89.         512,                 /* maximum number of MO's */
  90.         8,                   /* number of bytes per MO entry */
  91.         2,                   /* number of bytes between MO words */
  92.         0,                   /* ignore an entry if this word == 0xffff */
  93.         2, 3, 0x1ff,         /* link = (data[linkword] >> linkshift) & linkmask */
  94.         0                    /* render in reverse link order */
  95.     };
  96.  
  97.     static struct atarigen_pf_desc pf_desc =
  98.     {
  99.         16, 8,                /* width/height of each tile */
  100.         64, 64,                /* number of tiles in each direction */
  101.         1                    /* non-scrolling */
  102.     };
  103.  
  104.     /* reset statics */
  105.     memset(priority, 0, sizeof(priority));
  106.  
  107.     /* initialize the playfield */
  108.     if (atarigen_pf_init(&pf_desc))
  109.         return 1;
  110.  
  111.     /* initialize the motion objects */
  112.     if (atarigen_mo_init(&mo_desc))
  113.     {
  114.         atarigen_pf_free();
  115.         return 1;
  116.     }
  117.  
  118.     return 0;
  119. }
  120.  
  121.  
  122.  
  123. /*************************************
  124.  *
  125.  *    Video system shutdown
  126.  *
  127.  *************************************/
  128.  
  129. void blstroid_vh_stop(void)
  130. {
  131.     atarigen_pf_free();
  132.     atarigen_mo_free();
  133. }
  134.  
  135.  
  136.  
  137. /*************************************
  138.  *
  139.  *    Periodic scanline updater
  140.  *
  141.  *************************************/
  142.  
  143. static void irq_off(int param)
  144. {
  145.     atarigen_scanline_int_ack_w(0, 0);
  146. }
  147.  
  148.  
  149. void blstroid_scanline_update(int scanline)
  150. {
  151.     int offset = (scanline / 8) * 0x80 + 0x50;
  152.  
  153.     /* update motion objects */
  154.     if (scanline == 0)
  155.         atarigen_mo_update(atarigen_spriteram, 0, scanline);
  156.  
  157.     /* check for interrupts */
  158.     if (offset < atarigen_playfieldram_size)
  159.         if (READ_WORD(&atarigen_playfieldram[offset]) & 0x8000)
  160.         {
  161.             /* generate the interrupt */
  162.             atarigen_scanline_int_gen();
  163.             atarigen_update_interrupts();
  164.  
  165.             /* also set a timer to turn ourself off */
  166.             timer_set(cpu_getscanlineperiod(), 0, irq_off);
  167.         }
  168. }
  169.  
  170.  
  171.  
  172. /*************************************
  173.  *
  174.  *    Playfield RAM write handler
  175.  *
  176.  *************************************/
  177.  
  178. WRITE_HANDLER( blstroid_playfieldram_w )
  179. {
  180.     int oldword = READ_WORD(&atarigen_playfieldram[offset]);
  181.     int newword = COMBINE_WORD(oldword, data);
  182.  
  183.     if (oldword != newword)
  184.     {
  185.         WRITE_WORD(&atarigen_playfieldram[offset], newword);
  186.         atarigen_pf_dirty[offset / 2] = 1;
  187.     }
  188. }
  189.  
  190.  
  191.  
  192. /*************************************
  193.  *
  194.  *    Priority RAM write handler
  195.  *
  196.  *************************************/
  197.  
  198. WRITE_HANDLER( blstroid_priorityram_w )
  199. {
  200.     int shift, which;
  201.  
  202.     /* pick which playfield palette to look at */
  203.     which = (offset >> 5) & 7;
  204.  
  205.     /* upper 16 bits are for H == 1, lower 16 for H == 0 */
  206.     shift = (offset >> 4) & 0x10;
  207.     shift += (offset >> 1) & 0x0f;
  208.  
  209.     /* set or clear the appropriate bit */
  210.     priority[which] = (priority[which] & ~(1 << shift)) | ((data & 1) << shift);
  211. }
  212.  
  213.  
  214.  
  215. /*************************************
  216.  *
  217.  *    Main refresh
  218.  *
  219.  *************************************/
  220.  
  221. void blstroid_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh)
  222. {
  223.     /* remap if necessary */
  224.     if (update_palette())
  225.         memset(atarigen_pf_dirty, 1, atarigen_playfieldram_size / 2);
  226.  
  227.     /* draw the playfield */
  228.     atarigen_pf_process(pf_render_callback, bitmap, &Machine->drv->visible_area);
  229.  
  230.     /* render the motion objects */
  231.     atarigen_mo_process(mo_render_callback, bitmap);
  232.  
  233.     /* update onscreen messages */
  234.     atarigen_update_messages();
  235. }
  236.  
  237.  
  238.  
  239. /*************************************
  240.  *
  241.  *    Palette management
  242.  *
  243.  *************************************/
  244.  
  245. static const UINT8 *update_palette(void)
  246. {
  247.     UINT16 pf_map[8], mo_map[16];
  248.     int i, j;
  249.  
  250.     /* reset color tracking */
  251.     memset(mo_map, 0, sizeof(mo_map));
  252.     memset(pf_map, 0, sizeof(pf_map));
  253.     palette_init_used_colors();
  254.  
  255.     /* update color usage for the playfield */
  256.     atarigen_pf_process(pf_color_callback, pf_map, &Machine->drv->visible_area);
  257.  
  258.     /* update color usage for the mo's */
  259.     atarigen_mo_process(mo_color_callback, mo_map);
  260.  
  261.     /* rebuild the playfield palette */
  262.     for (i = 0; i < 8; i++)
  263.     {
  264.         UINT16 used = pf_map[i];
  265.         if (used)
  266.             for (j = 0; j < 16; j++)
  267.                 if (used & (1 << j))
  268.                     palette_used_colors[0x100 + i * 16 + j] = PALETTE_COLOR_USED;
  269.     }
  270.  
  271.     /* rebuild the motion object palette */
  272.     for (i = 0; i < 16; i++)
  273.     {
  274.         UINT16 used = mo_map[i];
  275.         if (used)
  276.         {
  277.             palette_used_colors[0x000 + i * 16 + 0] = PALETTE_COLOR_TRANSPARENT;
  278.             for (j = 1; j < 16; j++)
  279.                 if (used & (1 << j))
  280.                     palette_used_colors[0x000 + i * 16 + j] = PALETTE_COLOR_USED;
  281.         }
  282.     }
  283.  
  284.     return palette_recalc();
  285. }
  286.  
  287.  
  288.  
  289. /*************************************
  290.  *
  291.  *    Playfield palette
  292.  *
  293.  *************************************/
  294.  
  295. static void pf_color_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  296. {
  297.     const unsigned int *usage = Machine->gfx[0]->pen_usage;
  298.     UINT16 *colormap = param;
  299.     int x, y;
  300.  
  301.     /* standard loop over tiles */
  302.     for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  303.         for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  304.         {
  305.             int offs = y * 64 + x;
  306.             int data = READ_WORD(&atarigen_playfieldram[offs * 2]);
  307.             int code = data & 0x1fff;
  308.             int color = data >> 13;
  309.  
  310.             /* mark the colors used by this tile */
  311.             colormap[color] |= usage[code];
  312.         }
  313. }
  314.  
  315.  
  316.  
  317. /*************************************
  318.  *
  319.  *    Playfield rendering
  320.  *
  321.  *************************************/
  322.  
  323. static void pf_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  324. {
  325.     const struct GfxElement *gfx = Machine->gfx[0];
  326.     struct osd_bitmap *bitmap = param;
  327.     int x, y;
  328.  
  329.     /* standard loop over tiles */
  330.     for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  331.         for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  332.         {
  333.             int offs = y * 64 + x;
  334.  
  335.             /* update only if dirty */
  336.             if (atarigen_pf_dirty[offs])
  337.             {
  338.                 int data = READ_WORD(&atarigen_playfieldram[offs * 2]);
  339.                 int code = data & 0x1fff;
  340.                 int color = data >> 13;
  341.  
  342.                 drawgfx(atarigen_pf_bitmap, gfx, code, color, 0, 0, 16 * x, 8 * y, 0, TRANSPARENCY_NONE, 0);
  343.                 atarigen_pf_dirty[offs] = 0;
  344.             }
  345.         }
  346.  
  347.     /* then blast the result */
  348.     copybitmap(bitmap, atarigen_pf_bitmap, 0, 0, 0, 0, clip, TRANSPARENCY_NONE, 0);
  349. }
  350.  
  351.  
  352.  
  353. /*************************************
  354.  *
  355.  *    Playfield overrendering
  356.  *
  357.  *************************************/
  358.  
  359. static void pf_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  360. {
  361.     const struct GfxElement *gfx = Machine->gfx[0];
  362.     struct osd_bitmap *bitmap = param;
  363.     int x, y;
  364.  
  365.     /* standard loop over tiles */
  366.     for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  367.         for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  368.         {
  369.             int offs = y * 64 + x;
  370.             int data = READ_WORD(&atarigen_playfieldram[offs * 2]);
  371.             int color = data >> 13;
  372.  
  373.             /* overrender if there is a non-zero priority for this color */
  374.             /* not perfect, but works for the most obvious cases */
  375.             if (!priority[color])
  376.             {
  377.                 int code = data & 0x1fff;
  378.                 drawgfx(bitmap, gfx, code, color, 0, 0, 16 * x, 8 * y, clip, TRANSPARENCY_NONE, 0);
  379.             }
  380.         }
  381. }
  382.  
  383.  
  384.  
  385. /*************************************
  386.  *
  387.  *    Motion object palette
  388.  *
  389.  *************************************/
  390.  
  391. static void mo_color_callback(const UINT16 *data, const struct rectangle *clip, void *param)
  392. {
  393.     const unsigned int *usage = Machine->gfx[1]->pen_usage;
  394.     UINT16 *colormap = param;
  395.     int vsize = (data[0] & 0x000f) + 1;
  396.     int code = data[1] & 0x3fff;
  397.     int color = data[3] & 0x000f;
  398.     UINT16 temp = 0;
  399.     int i;
  400.  
  401.     for (i = 0; i < vsize; i++)
  402.         temp |= usage[code++];
  403.     colormap[color] |= temp;;
  404. }
  405.  
  406.  
  407.  
  408. /*************************************
  409.  *
  410.  *    Motion object rendering
  411.  *
  412.  *************************************/
  413.  
  414. static void mo_render_callback(const UINT16 *data, const struct rectangle *clip, void *param)
  415. {
  416.     const struct GfxElement *gfx = Machine->gfx[1];
  417.     struct osd_bitmap *bitmap = param;
  418.     struct rectangle pf_clip;
  419.  
  420.     /* extract data from the various words */
  421.     int ypos = -(data[0] >> 7);
  422.     int vsize = (data[0] & 0x000f) + 1;
  423.     int hflip = data[1] & 0x8000;
  424.     int vflip = data[1] & 0x4000;
  425.     int code = data[1] & 0x3fff;
  426.     int xpos = (data[3] >> 7) << 1;
  427.     int color = data[3] & 0x000f;
  428.  
  429.     /* adjust for height */
  430.     ypos -= vsize * 8;
  431.  
  432.     /* adjust the final coordinates */
  433.     xpos &= 0x3ff;
  434.     ypos &= 0x1ff;
  435.     if (xpos >= XDIM) xpos -= 0x400;
  436.     if (ypos >= YDIM) ypos -= 0x200;
  437.  
  438.     /* clip the X coordinate */
  439.     if (xpos <= -16 || xpos >= XDIM)
  440.         return;
  441.  
  442.     /* determine the bounding box */
  443.     atarigen_mo_compute_clip_16x8(pf_clip, xpos, ypos, 1, vsize, clip);
  444.  
  445.     /* draw the motion object */
  446.     atarigen_mo_draw_16x8_strip(bitmap, gfx, code, color, hflip, vflip, xpos, ypos, vsize, clip, TRANSPARENCY_PEN, 0);
  447.  
  448.     /* overrender the playfield */
  449.     atarigen_pf_process(pf_overrender_callback, bitmap, &pf_clip);
  450. }
  451.